﻿using DotNetty.Transport.Channels;
using MedianSocketService.netty;
using MedianSocketService.utils;
using System.Threading.Channels;

namespace MedianSocketService.services
{
    public class HighPowerProtocolService
    {
        #region ___字段___
        /// <summary>
        /// Socket字段
        /// </summary>
        public SocketClientInfo sci { get; set; }

        // 包头长度
        private const int HeaderLength = 14;
        // 包尾长度
        private const int FooterLength = 2;
        #endregion

        #region ___解数据包___
        /// <summary>
        /// 接包数据
        /// </summary>
        /// <param name="btFrameData"></param>
        public void UnPack(byte[] btFrameData)
        {
            if (btFrameData == null || btFrameData.Length < 14)
            {
                //一个完整的包最简单结构： 包头(13)+包体(*)+包尾(2)
                //包长度小于16 认为不是一个完整的包结构--下面使用到了 命令Command 所以在这里简单判断长度
                return;
            }
            /********复制出来包头、包体、包尾*************/
            var dataLength = new byte[4];
            //软件版本
            Array.Copy(btFrameData, 4, dataLength, 0, 2);
            var version = 0xff00 & dataLength[1] << 8 | 0xff & dataLength[0];
            //箱号
            Array.Copy(btFrameData, 6, dataLength, 0, 2);
            var caseNo = 0xff00 & dataLength[1] << 8 | 0xff & dataLength[0];
            //命令
            Array.Copy(btFrameData, 8, dataLength, 0, 2);
            var Command = 0xff00 & dataLength[1] << 8 | 0xff & dataLength[0];
            //长度
            Array.Copy(btFrameData, 10, dataLength, 0, 2);
            var DataLength = 0xff00 & dataLength[1] << 8 | 0xff & dataLength[0];
            //通道
            Array.Copy(btFrameData, 12, dataLength, 0, 2);
            var channelNo = 0xff00 & dataLength[1] << 8 | 0xff & dataLength[0];


            List<byte> byteData = new List<byte>();
            // 联机查询
            if (Command == 0x01FC)
            {
                sci.CmdName = "联机查询";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFC);
                byteData.Add(0x01);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x32);
                byteData.Add(0x00);
                //////通道个数////////
                byteData.AddRange(IntToByte4(1));
                //////AC模块/////////
                //最大输出电压
                byteData.AddRange(IntToByte2(10));
                //最大输出电流
                byteData.AddRange(IntToByte2(5));
                //DSP版本
                byteData.AddRange(IntToByte2(1));
                //CPLD版本
                byteData.AddRange(IntToByte2(1));
                //////DC模块/////////
                //预留
                byteData.AddRange(IntToByte2(0));
                //预留
                byteData.AddRange(IntToByte2(0));
                //DSP版本
                byteData.AddRange(IntToByte2(1));
                //CPLD版本
                byteData.AddRange(IntToByte2(1));
                //软件版本
                byteData.AddRange(IntToByte4(2));
                //硬件版本
                byteData.AddRange(IntToByte4(3));
                //编译时间
                byteData.AddRange(IntToByte4(4));
                //编译日期
                byteData.AddRange(IntToByte4(5));
                //协议版本
                byteData.AddRange(IntToByte4(6));
                //产品序列号低32位
                byteData.AddRange(IntToByte4(7));
                //产品序列号高32位
                byteData.AddRange(IntToByte4(8));

                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            // 采样
            else if (Command == 0x01FD)
            {
                sci.CmdName = "采样";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFD);
                byteData.Add(0x01);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0xEE);
                byteData.Add(0x00);

                Random random = new Random();
                for (int i = 14; i < 250; i++)
                {
                    // 设备类型
                    if (i == 14)
                        byteData.Add(0x01);
                    // BMS状态
                    else if (i == 18)
                        byteData.Add(0x02);
                    // 通道状态
                    else if (i == 22)
                        byteData.Add(0x03);
                    // 通道模式
                    else if (i == 26)
                        byteData.Add(0x04);
                    // 电压
                    else if (i == 30)
                        byteData.Add((byte)random.Next(5, 9));
                    // 电流
                    else if (i == 34)
                    {
                        var current = random.Next(1, 10);
                        byteData.Add((byte)current);
                    }
                    // 控制单元状态
                    else if (i == 38)
                        byteData.Add(0x01);
                    // 控制单元标识
                    else if (i == 42)
                        byteData.Add(0x02);
                    // 控制单元IO状态
                    else if (i == 46)
                        byteData.Add(0x09);
                    // 电位均衡电阻值
                    else if (i == 50)
                        byteData.Add(0x10);
                    // 正对值电阻
                    else if (i == 54)
                        byteData.Add(0x11);
                    // 负对值电阻
                    else if (i == 58)
                        byteData.Add(0x12);
                    // 充电枪温度
                    else if (i == 62)
                        byteData.Add(0x13);
                    // 环境温度
                    else if (i == 66)
                        byteData.Add(0x14);
                    // 模块温度
                    else if (i == 70)
                        byteData.Add(0x15);
                    // 最高允许充电总电压
                    else if (i == 74)
                        byteData.Add(0x16);
                    // 最高允许充电总电流
                    else if (i == 78)
                        byteData.Add(0x17);
                    // 最高允许温度
                    else if (i == 82)
                        byteData.Add(0x18);
                    // 单体动力蓄电池最高允许充电电压
                    else if (i == 86)
                        byteData.Add(0x19);
                    // 充电电压需求
                    else if (i == 90)
                        byteData.Add(0x20);
                    // 充电电流需求
                    else if (i == 94)
                        byteData.Add(0x21);
                    // 充电模式
                    else if (i == 98)
                        byteData.Add(0x22);
                    // 充电电压测量值
                    else if (i == 102)
                        byteData.Add(0x23);
                    // 充电电流测量值
                    else if (i == 106)
                        byteData.Add(0x24);
                    // 整车动力蓄电池荷电状态
                    else if (i == 110)
                        byteData.Add(0x25);
                    // 整车动力蓄电池当前电池电压
                    else if (i == 114)
                        byteData.Add(0x26);
                    // 动力蓄电池标称总能量
                    else if (i == 118)
                        byteData.Add(0x27);
                    // 最高单体动力蓄电池电压
                    else if (i == 122)
                        byteData.Add(0x28);
                    // 最高单体动力蓄电池组号
                    else if (i == 126)
                        byteData.Add(0x29);
                    // 最高单体动力蓄电池编号
                    else if (i == 130)
                        byteData.Add(0x30);
                    // 当前荷电状态SOC(%)
                    else if (i == 134)
                        byteData.Add(0x31);
                    // 估算剩余充电时间
                    else if (i == 138)
                        byteData.Add(0x32);
                    // 最高动力蓄电池温度
                    else if (i == 142)
                        byteData.Add(0x33);
                    // 最高温度检测点编号
                    else if (i == 146)
                        byteData.Add(0x34);
                    // 最低动力蓄电池温度
                    else if (i == 150)
                        byteData.Add(0x35);
                    // 最低温度检测点编号
                    else if (i == 154)
                        byteData.Add(0x36);
                    // 单体动力蓄电池电压状态
                    else if (i == 158)
                        byteData.Add(0x37);
                    // 整车动力蓄电池荷电状态SOC
                    else if (i == 162)
                        byteData.Add(0x38);
                    else
                        byteData.Add(0x00);
                }
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            // 安全参数
            else if (Command == 0x01FB)
            {
                sci.CmdName = "安全参数";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFB);
                byteData.Add(0x01);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x26);
                byteData.Add(0x00);

                for (int i = 0; i < 36; i++)
                    byteData.Add(0x00);

                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            //恒流恒压充电
            else if (Command == 0x05FF)
            {
                sci.CmdName = "恒流恒压充电";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFF);
                byteData.Add(0x05);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x02);
                byteData.Add(0x00);
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            //恒流恒压放电
            else if (Command == 0x06FF)
            {
                sci.CmdName = "恒流恒压放电";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFF);
                byteData.Add(0x06);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x02);
                byteData.Add(0x00);
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            //恒流放电
            else if (Command == 0x01FF)
            {
                sci.CmdName = "恒流放电";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFF);
                byteData.Add(0x01);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x02);
                byteData.Add(0x00);
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            //恒流充电
            else if (Command == 0x02FF)
            {
                sci.CmdName = "恒流充电";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFF);
                byteData.Add(0x02);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x02);
                byteData.Add(0x00);
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            //闪灯
            else if (Command == 0x0FFF)
            {
                sci.CmdName = "闪灯";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFF);
                byteData.Add(0x0F);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x03);
                byteData.Add(0x00);
                //////亮起通道号////////
                byteData.Add(0x01);
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            //停止闪灯
            else if (Command == 0x10FF)
            {
                sci.CmdName = "停止闪灯";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFF);
                byteData.Add(0x10);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x03);
                byteData.Add(0x00);
                //////亮起通道号////////
                byteData.Add(0x01);
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            // 电位均衡测试
            else if (Command == 0x11FF)
            {
                sci.CmdName = "电位均衡测试";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFF);
                byteData.Add(0x11);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x03);
                byteData.Add(0x00);
                //////亮起通道号////////
                byteData.Add(0x01);
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            // 绝缘监测测试
            else if (Command == 0x12FF)
            {
                sci.CmdName = "绝缘监测测试";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFF);
                byteData.Add(0x12);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x03);
                byteData.Add(0x00);
                //////亮起通道号////////
                byteData.Add(0x01);
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            // 停机
            else if (Command == 0x0AFF)
            {
                sci.CmdName = "停机";
                //////指令头///////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(caseNo));
                //////命令码////////
                byteData.Add(0xFF);
                byteData.Add(0x0A);
                //////通道////////
                byteData.AddRange(IntToByte2(channelNo));
                //////长度////////
                byteData.Add(0x02);
                byteData.Add(0x00);
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            // 网络设置
            else if (Command == 0x01FE)
            {
                sci.CmdName = "网络设置";
                //////命令头////////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(1));
                //////命令码////////
                byteData.Add(0xFE);
                byteData.Add(0x01);
                //////通道////////
                byteData.AddRange(IntToByte2(1));
                //////长度////////
                byteData.AddRange(IntToByte2(2));
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            // BMS充电结束查询统计
            else if (Command == 0x03FA)
            {
                sci.CmdName = "BMS充电结束查询统计";
                //////命令头////////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(1));
                //////命令码////////
                byteData.Add(0xFA);
                byteData.Add(0x03);
                //////通道////////
                byteData.AddRange(IntToByte2(1));
                //////长度////////
                byteData.AddRange(IntToByte2(9));
                //////数据////////
                byteData.Add(0x01);
                //////数据-单体最低电压////////
                byteData.AddRange(IntToByte2(1));
                //////数据-单体最高电压////////
                byteData.AddRange(IntToByte2(9));
                //////数据-动力蓄电池最低温度////////
                byteData.Add(0x01);
                //////数据-动力蓄电池最高温度////////
                byteData.Add(0x16);
                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            // BMS参数查询统计
            else if (Command == 0x01FA)
            {
                sci.CmdName = "BMS参数查询统计";
                //////命令头////////
                byteData.AddRange(Header());
                //////版本号///////
                byteData.Add(0x22);
                byteData.Add(0x00);
                //////设备地址////////
                byteData.AddRange(IntToByte2(1));
                //////命令码////////
                byteData.Add(0xFA);
                byteData.Add(0x01);
                //////通道////////
                byteData.AddRange(IntToByte2(1));
                //////长度////////
                byteData.AddRange(IntToByte2(24));
                //////版本////////
                byteData.Add(0x01);
                byteData.Add(0x01);
                byteData.Add(0x01);
                //////电池类型////////
                byteData.Add(0x01);
                //////数据-额定容量////////
                byteData.AddRange(IntToByte2(200));
                //////数据-额定电压////////
                byteData.Add(0x10);
                byteData.Add(0x01);

                //22
                byteData.Add(0x00);
                //23
                byteData.Add(0x00);
                //24
                byteData.Add(0x00);
                //25
                byteData.Add(0x00);
                //26
                byteData.Add(0x00);
                //27
                byteData.Add(0x00);
                //28
                byteData.Add(0x00);
                //29
                byteData.Add(0x00);
                //30
                byteData.Add(0x00);
                //31
                byteData.Add(0x00);
                //32
                byteData.Add(0x00);
                //////充电次数////////
                byteData.Add(0xff);
                byteData.Add(0xff);
                byteData.Add(0xff);

                //////验证码////////
                byteData.Add(0xfe);
                byteData.Add(0xfe);
            }
            ChannelManager.GetInstance().SendDataToClient(sci, byteData.ToArray());
        }
        #endregion

        #region __报文头__
        /// <summary>
        /// 报文头
        /// </summary>
        /// <returns></returns>
        private List<byte> Header()
        {
            List<byte> header = new List<byte>();
            header.Add(0xFF);
            header.Add(0x55);
            header.Add(0xAA);
            header.Add(0xFF);
            return header;
        }
        #endregion

        #region ___CRC校验码和转换___
        /// <summary>
        /// 整型转字节,低字节在前-高字节在后
        /// </summary>
        /// <param name="caseNo"></param>
        /// <returns></returns>
        public virtual List<byte> IntToByte2(int data)
        {
            List<byte> address = new List<byte>();
            var udataLength = (ushort)(data);
            address.Add((byte)(0xff & udataLength));
            address.Add((byte)((0xff00 & udataLength) >> 8));
            return address;
        }
        /// <summary>
        /// 整型转字节
        /// </summary>
        /// <param name="caseNo"></param>
        /// <returns></returns>
        public virtual List<byte> IntToByte4(int data)
        {
            List<byte> address = new List<byte>();
            address.Add((byte)(0xff & data));
            address.Add((byte)((0xff00 & data) >> 8));
            address.Add((byte)((0xff00 & data) >> 16));
            address.Add((byte)((0xff00 & data) >> 24));
            return address;
        }
        /// <summary>
        /// 整型转字节
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public virtual List<byte> DoubleToByte2(double data)
        {
            var intData = Math.Round(data, MidpointRounding.AwayFromZero);
            List<byte> address = new List<byte>();
            var udataLength = (int)(intData);
            address.Add((byte)((0xff00 & udataLength) >> 8));
            address.Add((byte)(0xff & udataLength));
            return address;
        }
        /// <summary>
        /// 整型转字节
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public virtual List<byte> DoubleToByte4(double data)
        {
            var intData = Math.Round(data, MidpointRounding.AwayFromZero);
            List<byte> address = new List<byte>();
            var udataLength = (int)(intData);
            address.Add((byte)((0xff000000 & udataLength) >> 24));
            address.Add((byte)((0xff0000 & udataLength) >> 16));
            address.Add((byte)((0xff00 & udataLength) >> 8));
            address.Add((byte)(0xff & udataLength));
            return address;
        }
        public byte[] Crc16(byte[] puchMsg)
        {
            return CRCHelper.Crc16_2(puchMsg);
        }
        #endregion
    }
}